package com.rfid.webp2plib;

import android.util.Log;

import androidx.annotation.NonNull;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import org.json.JSONException;
import org.json.JSONObject;
import org.webrtc.IceCandidate;
import org.webrtc.SessionDescription;

import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;

/**
 * Created by deanliu on 2019/9/4.
 */

public class SignalClient {

    private static final String TAG = "SignalClient:webrtc";
//    private final static String mSocketAddress = "http://10.200.74.140:3000/";
    private final static String mSocketAddress = "http://2.tcp.cpolar.cn:12434";

    private Socket mClient;
    private String mClientId;

    private List<SignalListener> mSignalListeners;
    private UserListener mUserListener;

    public SignalClient() {
        mSignalListeners = new ArrayList<>();
        try {
            mClient = IO.socket(mSocketAddress);
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        mClient.on("signal", messageListener);
        mClient.on("login",mLoginListener);
        mClient.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                mClientId = mClient.id();
                if (mUserListener != null) {
                    mUserListener.onConnect(mClientId);
                }
            }
        });
        mClient.on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                if (mUserListener != null) {
                    mUserListener.onDisconnect();
                }
            }
        });
        Log.v(TAG,"SignalClient construct");
    }

    public boolean isConnect() {
        return mClient.connected();
    }

    public void registerSignalListener(@NonNull SignalListener signalListener) {
        mSignalListeners.add(signalListener);
    }

    public void setUserListener(@NonNull UserListener listener) {
        mUserListener = listener;
    }

    public void unRegisterSignaListener(SignalListener listener) {
        mSignalListeners.remove(listener);
    }

    public String getId() {
        return mClientId;
    }

    public void connectSignalServer() {
        Log.v(TAG,"connectSignalServer");
        mClient.connect(); //onLogin
    }

    public void release() {
        mUserListener = null;
        mSignalListeners.clear();
        mClient.off();
        mClient.disconnect();
        mClient.close();
        mClient = null;
    }

    private Emitter.Listener mLoginListener = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            String json = args[0].toString();
            Log.d(TAG, "mLoginListener json : " + json);
            Gson gson = new Gson();
            List<User> users = gson.fromJson(json, new TypeToken<List<User>>(){}.getType());
            if (mUserListener != null) {
                mUserListener.onLogin(mClientId, users);
            }
        }
    };

    private Emitter.Listener messageListener = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            JSONObject data = (JSONObject) args[0];
            Log.d(TAG, "messageListener call data : " + data);
            try {
                String from = data.getString("from");
                String type = data.getString("type");
                JSONObject payload = null;
                if (!type.equals("init") && !type.equals("login") && !type.equals("leave")) {
                    payload = data.getJSONObject("payload");
                }
                switch (type) {
                    case "offer":
                        SessionDescription sdp = new SessionDescription(
                                SessionDescription.Type.fromCanonicalForm(payload.getString("type")),
                                payload.getString("sdp"));
                        for(SignalListener signalListener:mSignalListeners) {
                            signalListener.onOffer(from,sdp);
                        }
                        break;                                                                                           
                    case "answer":
                         sdp = new SessionDescription(
                                SessionDescription.Type.fromCanonicalForm(payload.getString("type")),
                                payload.getString("sdp"));
                        for(SignalListener signalListener:mSignalListeners) {
                            signalListener.onAnswer(from,sdp);
                        }
                        break;
                    case "candidate":
                        IceCandidate candidate = new IceCandidate(
                                payload.getString("id"),
                                payload.getInt("label"),
                                payload.getString("candidate"));
                        for(SignalListener signalListener:mSignalListeners) {
                            signalListener.onCandidate(from,candidate);
                        }
                        break;
                    default:
                        break;
                }

            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    };
    public void sendMessage(String to, String type, JSONObject payload) throws JSONException {
        Log.i(TAG,"sendMessage:" + type);
        JSONObject message = new JSONObject();
        message.put("to", to);
        message.put("type", type);
        message.put("payload", payload);
        message.put("from", mClientId);
        mClient.emit("signal", message);
    }

    public void login(String message) {
        mClient.emit("login", message);
    }


    public interface UserListener{
        public void onLogin(String id, List<User> users);

        public void onConnect(String id);

        public void onDisconnect();
    }

    public interface SignalListener{
        public void onOffer(String from, SessionDescription sdp);
        public void onAnswer(String from, SessionDescription sdp);
        public void onCandidate(String from, IceCandidate candidate);
    }
}
